from abc import ABCMeta, abstractmethod
import time

'''
别名：监听模式、观察者模式、推拉模型、订阅模式（一对多）
被观察者的三个方法：添加观察者、移出观察者、通知观察者
观察者的一个方法：更新方法
每当被观察者的状态发生改变时，就会通知观察者，观察者就会判断被观察者的状态是否达到自己需要响应的标准，从而响应或者不响应
'''


class Observer(metaclass=ABCMeta):
    '''观察者的基类'''
    @abstractmethod
    def update(self, observable, object):
        pass


class Observable:
    '''被观察者的基类'''
    def __init__(self):
        self.__observers = []

    def removeObserver(self, observer):
        self.__observers.remove(observer)

    def addObserver(self, observer):
        self.__observers.append(observer)

    def notifyObservers(self):
        for observer in self.__observers:
            observer.update(self)


class WaterHeater(Observable):
    '''热水器'''
    def __init__(self):
        super().__init__()
        self.__temperature = 25
    
    def setTemperature(self, temperature):
        if temperature > 100:
            temperature = 100
        # 每当状态发生改变时，就要通知被观察者，至于被观察者响不响应就是另一回事了
        self.__temperature = temperature
        self.notifyObservers()

    def getTemperature(self):
        print("现在水温是", self.__temperature, "度")
        return self.__temperature


class WashMode(Observer):
    '''洗澡模式'''
    def update(self, observable):
        if observable.getTemperature() > 50 and observable.getTemperature() < 70:
            print("水已经烧好！温度正好，可以用来洗澡了。")


class DrinkMode(Observer):
    '''饮用模式'''
    def update(self, observable):
        if observable.getTemperature() == 100:
            print("水已经烧好！可以放心饮用了。")



if __name__ == "__main__":
    heater = WaterHeater()
    washObser = WashMode()
    drinkObser = DrinkMode()
    heater.addObserver(washObser)
    heater.addObserver(drinkObser)
    for i in range(1000):
        time.sleep(0.1)
        heater.setTemperature(i)
        heater.getTemperature()